using System;
using System.Collections.Generic;
using System.Linq; // Added for .Count()

namespace MinesweeperGame
{
    /// <summary>
    /// 游戏引擎类，管理扫雷游戏的核心逻辑
    /// </summary>
    public class GameEngine
    {
        /// <summary>
        /// 游戏状态
        /// </summary>
        public GameState State { get; private set; }

        /// <summary>
        /// 当前难度
        /// </summary>
        public Difficulty Difficulty { get; private set; }

        /// <summary>
        /// 游戏板
        /// </summary>
        public GameBoard Board { get; private set; }

        /// <summary>
        /// 游戏开始时间
        /// </summary>
        public DateTime StartTime { get; private set; }

        /// <summary>
        /// 游戏结束时间
        /// </summary>
        public DateTime EndTime { get; private set; }

        /// <summary>
        /// 游戏时长（秒）
        /// </summary>
        public int GameTime
        {
            get
            {
                if (State == GameState.NotStarted)
                    return 0;
                
                var endTime = State == GameState.Playing ? DateTime.Now : EndTime;
                return (int)(endTime - StartTime).TotalSeconds;
            }
        }

        /// <summary>
        /// 是否为第一次点击
        /// </summary>
        public bool IsFirstClick { get; private set; }

        /// <summary>
        /// 游戏状态改变事件
        /// </summary>
        public event EventHandler<GameStateChangedEventArgs> GameStateChanged;

        /// <summary>
        /// 方块状态改变事件
        /// </summary>
        public event EventHandler<CellChangedEventArgs> CellChanged;

        /// <summary>
        /// 构造函数
        /// </summary>
        public GameEngine()
        {
            State = GameState.NotStarted;
            IsFirstClick = true;
        }

        /// <summary>
        /// 初始化游戏
        /// </summary>
        /// <param name="difficulty">游戏难度</param>
        public void InitializeGame(Difficulty difficulty)
        {
            Difficulty = difficulty;
            int rows, cols, mineCount;

            switch (difficulty)
            {
                case Difficulty.Beginner:
                    rows = 9;
                    cols = 9;
                    mineCount = 10;
                    break;
                case Difficulty.Intermediate:
                    rows = 16;
                    cols = 16;
                    mineCount = 40;
                    break;
                case Difficulty.Expert:
                    rows = 16;
                    cols = 30;
                    mineCount = 99;
                    break;
                default:
                    throw new ArgumentException("不支持的难度级别");
            }

            Board = new GameBoard(rows, cols, mineCount);
            State = GameState.NotStarted;
            IsFirstClick = true;
            StartTime = DateTime.MinValue;
            EndTime = DateTime.MinValue;

            OnGameStateChanged();
        }

        /// <summary>
        /// 初始化自定义游戏
        /// </summary>
        /// <param name="rows">行数</param>
        /// <param name="cols">列数</param>
        /// <param name="mineCount">地雷数量</param>
        public void InitializeCustomGame(int rows, int cols, int mineCount)
        {
            if (rows < 5 || rows > 30 || cols < 5 || cols > 30)
                throw new ArgumentException("网格大小必须在5x5到30x30之间");

            if (mineCount < 1 || mineCount >= rows * cols)
                throw new ArgumentException("地雷数量无效");

            Difficulty = Difficulty.Custom;
            Board = new GameBoard(rows, cols, mineCount);
            State = GameState.NotStarted;
            IsFirstClick = true;
            StartTime = DateTime.MinValue;
            EndTime = DateTime.MinValue;

            OnGameStateChanged();
        }

        /// <summary>
        /// 开始新游戏
        /// </summary>
        public void NewGame()
        {
            if (Board == null)
                throw new InvalidOperationException("请先初始化游戏");

            Board.Reset();
            State = GameState.NotStarted;
            IsFirstClick = true;
            StartTime = DateTime.MinValue;
            EndTime = DateTime.MinValue;

            OnGameStateChanged();
        }

        /// <summary>
        /// 揭开方块
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        /// <returns>操作结果</returns>
        public RevealResult RevealCell(int row, int col)
        {
            if (State != GameState.NotStarted && State != GameState.Playing)
                return RevealResult.InvalidState;

            if (Board == null)
                return RevealResult.InvalidState;

            // 第一次点击
            if (IsFirstClick)
            {
                Board.PlaceMines(row, col);
                StartTime = DateTime.Now;
                State = GameState.Playing;
                IsFirstClick = false;
                OnGameStateChanged();
            }

            // 检查是否踩到地雷
            bool hitMine = Board.RevealCell(row, col);
            
            if (hitMine)
            {
                State = GameState.Lost;
                EndTime = DateTime.Now;
                OnGameStateChanged();
                return RevealResult.HitMine;
            }

            // 检查是否获胜
            if (Board.IsGameWon())
            {
                State = GameState.Won;
                EndTime = DateTime.Now;
                OnGameStateChanged();
                return RevealResult.GameWon;
            }

            // 通知方块状态改变
            OnCellChanged(row, col, OperationType.Reveal);
            return RevealResult.Success;
        }

        /// <summary>
        /// 标记/取消标记方块
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        /// <returns>操作结果</returns>
        public FlagResult ToggleFlag(int row, int col)
        {
            if (State != GameState.NotStarted && State != GameState.Playing)
                return FlagResult.InvalidState;

            if (Board == null)
                return FlagResult.InvalidState;

            var cell = Board.Cells[row, col];
            if (cell.IsRevealed)
                return FlagResult.CellAlreadyRevealed;

            bool wasFlagged = cell.IsFlagged;
            Board.ToggleFlag(row, col);

            // 通知方块状态改变
            OnCellChanged(row, col, wasFlagged ? OperationType.Unflag : OperationType.Flag);
            
            // 检查是否获胜（通过标记所有地雷）
            if (Board.IsGameWon())
            {
                State = GameState.Won;
                EndTime = DateTime.Now;
                OnGameStateChanged();
            }
            
            return FlagResult.Success;
        }

        /// <summary>
        /// 快速展开（双击功能）
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        /// <returns>操作结果</returns>
        public RevealResult QuickReveal(int row, int col)
        {
            if (State != GameState.Playing)
                return RevealResult.InvalidState;

            if (row < 0 || row >= Board.Rows || col < 0 || col >= Board.Cols)
                return RevealResult.InvalidOperation;

            var cell = Board.Cells[row, col];
            if (!cell.IsRevealed || cell.AdjacentMineCount == 0)
                return RevealResult.InvalidOperation;

            // 检查周围标记的地雷数量是否等于数字
            var adjacentCells = Board.GetAdjacentCells(row, col);
            var flaggedCount = adjacentCells.Count(c => c.IsFlagged);
            
            if (flaggedCount != cell.AdjacentMineCount)
                return RevealResult.InvalidOperation;

            // 展开所有未标记的相邻方块
            bool hitMine = false;
            foreach (var adjacentCell in adjacentCells)
            {
                if (!adjacentCell.IsFlagged && !adjacentCell.IsRevealed)
                {
                    var result = RevealCell(adjacentCell.Row, adjacentCell.Col);
                    if (result == RevealResult.HitMine)
                    {
                        hitMine = true;
                    }
                }
            }

            if (hitMine)
            {
                State = GameState.Lost;
                EndTime = DateTime.Now;
                OnGameStateChanged();
                return RevealResult.HitMine;
            }

            // 检查是否获胜
            if (Board.IsGameWon())
            {
                State = GameState.Won;
                EndTime = DateTime.Now;
                OnGameStateChanged();
                return RevealResult.GameWon;
            }

            return RevealResult.Success;
        }

        /// <summary>
        /// 暂停游戏
        /// </summary>
        public void PauseGame()
        {
            if (State == GameState.Playing)
            {
                State = GameState.Paused;
                OnGameStateChanged();
            }
        }

        /// <summary>
        /// 继续游戏
        /// </summary>
        public void ResumeGame()
        {
            if (State == GameState.Paused)
            {
                State = GameState.Playing;
                OnGameStateChanged();
            }
        }

        /// <summary>
        /// 检查游戏是否获胜
        /// </summary>
        /// <returns>是否获胜</returns>
        public bool IsGameWon()
        {
            return State == GameState.Won;
        }

        /// <summary>
        /// 检查游戏是否失败
        /// </summary>
        /// <returns>是否失败</returns>
        public bool IsGameLost()
        {
            return State == GameState.Lost;
        }

        /// <summary>
        /// 触发游戏状态改变事件
        /// </summary>
        protected virtual void OnGameStateChanged()
        {
            GameStateChanged?.Invoke(this, new GameStateChangedEventArgs(State, GameTime));
        }

        /// <summary>
        /// 触发方块状态改变事件
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        /// <param name="operationType">操作类型</param>
        protected virtual void OnCellChanged(int row, int col, OperationType operationType)
        {
            CellChanged?.Invoke(this, new CellChangedEventArgs(row, col, operationType));
        }
    }

    /// <summary>
    /// 揭开方块结果枚举
    /// </summary>
    public enum RevealResult
    {
        Success,
        HitMine,
        GameWon,
        InvalidState,
        InvalidOperation
    }

    /// <summary>
    /// 标记方块结果枚举
    /// </summary>
    public enum FlagResult
    {
        Success,
        InvalidState,
        CellAlreadyRevealed
    }

    /// <summary>
    /// 游戏状态改变事件参数
    /// </summary>
    public class GameStateChangedEventArgs : EventArgs
    {
        public GameState NewState { get; }
        public int GameTime { get; }

        public GameStateChangedEventArgs(GameState newState, int gameTime)
        {
            NewState = newState;
            GameTime = gameTime;
        }
    }

    /// <summary>
    /// 方块状态改变事件参数
    /// </summary>
    public class CellChangedEventArgs : EventArgs
    {
        public int Row { get; }
        public int Col { get; }
        public OperationType OperationType { get; }

        public CellChangedEventArgs(int row, int col, OperationType operationType)
        {
            Row = row;
            Col = col;
            OperationType = operationType;
        }
    }
} 